Skip to content

release: 0.6.1 — publish the runtime VERSION export - #38

Merged
laynepenney merged 5 commits into
mainfrom
dev
Jul 30, 2026
Merged

release: 0.6.1 — publish the runtime VERSION export#38
laynepenney merged 5 commits into
mainfrom
dev

Conversation

@laynepenney

Copy link
Copy Markdown
Member

Release 0.6.1. Publishes the runtime VERSION export (TS + Python) that the intelligence contract requires — installed 0.6.0 exports undefined, which the contract's own gate rejects for any real consumer. Also lands extract_batch (synthetic fixtures) already on dev.

Two-agent release gate: Opus (r1) + Sentinel (r2) confirmed benign — gitleaks 0 hard / negative-control fired, fixture synthetic (0 PII, 0 identity/client terms). Merge-commit only. After merge: gh release create v0.6.1 + fresh-install fruit-check (VERSION must print 0.6.1).

laynepenney and others added 5 commits July 30, 2026 06:57
test(extract): synthetic fixture subject matter
Adds `VERSION` (TypeScript) and `__version__` (Python) so a consumer can read
which version of this package produced a document instead of hand-copying a
version string into its own constant.

WHY

A consumer that records extraction provenance needs the producing module's
version. Until now the package offered no way to obtain it, so hand-copying was
the only option available -- and a hand-copied version is a claim about the
runtime rather than evidence of it. One downstream consumer did exactly that and
its copy went stale, declaring 0.5.0 while 0.6.0 was current, with nothing able
to detect the drift. Asking consumers to keep a copy in sync is not a fix; it is
the same failure deferred. Making the version readable removes the need.

The IL already has a producer-provenance field (`produced_by`). This gives
consumers the value that belongs in it.

WHY A LITERAL AND NOT A READ OF package.json

The default TypeScript entry must stay importable in browser and WASM hosts;
`scripts/check-ts-universal-entry.mjs` fails the build if it reaches a Node
built-in. So `VERSION` is an embedded literal, the same trade the embedded
prompt fragments already make -- and it carries the same obligation an embedded
copy always carries: a test that fails when it drifts from its source.

DRIFT COVERAGE

The version is now written in four places (two manifests, two runtime
constants). `packages/ts/tests/test_version.ts` and
`tests/python/test_version.py` tie all four together, including across
languages: the two surfaces ship as one product at one version, and nothing
enforced that before -- they were two hand-edited numbers that happened to
agree.

Proven by mutation rather than asserted. Each of the four locations was mutated
in turn and a named test went red; both suites return green on restore:

  mutate ts/package.json      -> pytest RED, vitest RED   (cross-language tie)
  mutate python pyproject     -> pytest RED, vitest RED   (cross-language tie)
  mutate ts src/version.ts    -> vitest RED
  mutate python __init__.py   -> pytest RED

The Python suite also compares `importlib.metadata` against the source
constant. That reads what pip actually installed, which is a genuinely
different source than the literal, so it catches a stale editable install or a
bump that was never reinstalled -- something the other assertions cannot see.
It skips rather than fails when no distribution is installed, since importing
from a source tree is legitimate.

A note for whoever runs the mutation proof next: clear `__pycache__` between
steps. Bytecode invalidation compares source mtime at one-second granularity
plus size, and two same-length version edits inside the same second are
indistinguishable to it -- a stale `.pyc` served a mutated value after the file
had been restored. The masking is silent and it cuts both ways, so a mutation
result gathered without clearing the cache proves nothing.

scripts/bump-version.sh

Four hand-edited numbers is the shape that drifts, and this commit takes it
from two to four, so the tooling comes with it. The script updates all four,
rejects anything that is not a bare semver triple (a range or a full specifier
would each be a plausible paste and each would corrupt recorded provenance),
and verifies afterward that the four agree rather than reporting success for
having run.

It deliberately does not commit, tag, or push: under the dev/main model a tag
belongs to the release ceremony on main, not to whatever branch is checked out
when someone bumps a number.

Premium boundary: extract is OSS. A package's own version is public by
definition; no premium, identity, or org semantics are involved.
feat: expose the package version at runtime (VERSION + __version__)
@laynepenney
laynepenney merged commit 45d3a08 into main Jul 30, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant